/******************************************************************************************************************************************************************************************
 * @file   : SysInit.c
 * @brief  :
 * @author : STEF
 *=========================================================================================================================================================================================
 *                                                   Revision control History
 *=========================================================================================================================================================================================
 * V1.0.0: 2023-06-30 : Initial Version
 *
 *
 *****************************************************************************************************************************************************************************************/

/******************************************************************************************************************************************************************************************
 * Other header files
 *****************************************************************************************************************************************************************************************/
#include "fm33le0xxa_fl.h"
#include "svd.h"
#include "stdint.h"
#include "gptim.h"
#include "clock.h"
#include "rmu.h"
#include "pll.h"

#include "Sch.h"
#include "SysInit.h"
#include "SensorGroup.h"
#include "Led_app.h"




/* 捕获值 */
static uint32_t getccvLow = 0UL;
static uint32_t getccvHigh = 0UL;
static uint32_t ccvValNow = 0UL;
static uint32_t ccvValPrev = 0UL;

/* 识别左右边灯具 */
uint8_t Left_or_Right = 0;


/* DMA中读取的AD值 */
uint16_t DMAResult[ADC_Input_Number] = {0};           /* DMA读取的AD值 */
volatile unsigned char ADC_IntFinishFlag = 1;         /* 中断完成标志位 */
uint8_t ADC_TimeOutFlag = 0;                          /* 中断超时标志位 */
/**************************************************ADC function**************************************************/

/*****************************************************************************
 * 函数:ADC_Init
 * 功能:ADC初始化配置
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void ADC_Init(void)
{
    FL_GPIO_InitTypeDef         GPIO_InitStruct = {0};
    FL_ADC_CommonInitTypeDef    ADC_CommonInitStruct;
    FL_ADC_InitTypeDef          ADC_InitStruct;

    GPIO_InitStruct.pin = TAIL_SIG_PIN | STOP_SIG_PIN;       /* 配置引脚为模拟功能 PD0 CH3   PD1 CH4 */
    GPIO_InitStruct.mode = FL_GPIO_MODE_ANALOG;                             /* 功能模式 */
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;                   /* 输出类型 */
    GPIO_InitStruct.pull = FL_DISABLE;                                      /* 上拉使能 */  
    GPIO_InitStruct.remapPin = FL_DISABLE;                                  /* 数字功能重定向 */
    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* ADC 时钟配置 */
    ADC_CommonInitStruct.clockSource = FL_RCC_ADC_CLK_SOURCE_PLL;          /* ADC_CLK 时钟源 */
    ADC_CommonInitStruct.clockPrescaler = FL_RCC_ADC_PSC_DIV8;              /* ADC_CLK 分频系数 */

    FL_ADC_CommonInit(&ADC_CommonInitStruct);

    /* ADC寄存器设置 */
    ADC_InitStruct.conversionMode = FL_ADC_CONV_MODE_SINGLE;                 /* 单次模式 */
    ADC_InitStruct.autoMode = FL_ADC_SINGLE_CONV_MODE_AUTO;                  /* 自动 */
    ADC_InitStruct.waitMode = FL_DISABLE;                                    /* 等待 */
    ADC_InitStruct.overrunMode = FL_ENABLE;                                  /* 覆盖上次数据 */
    ADC_InitStruct.scanDirection = FL_ADC_SEQ_SCAN_DIR_FORWARD;              /* 通道正序扫描 */
    ADC_InitStruct.externalTrigConv = FL_ADC_TRIGGER_EDGE_NONE;              /* 禁止触发信号 */
    ADC_InitStruct.triggerSource = FL_ADC_TRGI_PA8;                          /* 触发信号选择 */
    ADC_InitStruct.fastChannelTime = FL_ADC_FAST_CH_SAMPLING_TIME_2_ADCCLK;  /* 快速通道采样时间 */
    ADC_InitStruct.lowChannelTime = FL_ADC_SLOW_CH_SAMPLING_TIME_192_ADCCLK; /* 慢速通道采样时间 */
    ADC_InitStruct.oversamplingMode = FL_DISABLE;                             /* 过采样打开 关闭可缩短采样时间 */
    ADC_InitStruct.overSampingMultiplier = FL_ADC_OVERSAMPLING_MUL_8X;       /* 8倍过采样 */
    ADC_InitStruct.oversamplingShift = FL_ADC_OVERSAMPLING_SHIFT_3B;         /* 数据右移*/

    FL_ADC_Init(ADC, &ADC_InitStruct);

    FL_ADC_EnableDMAReq(ADC);                                                /* 使能DMA请求 */
}

/**************************************************DMA function**************************************************/

/*****************************************************************************
 * 函数:ADC_DMA
 * 功能:ADC_DMA初始化配置
 * 参数:
 * 返回:
 * 说明:只有FL_DMA_CHANNEL_0和FL_DMA_CHANNEL_4能够用于ADC
 ****************************************************************************/
void ADC_DMA(uint16_t *buffer , uint32_t length)
{
    FL_DMA_InitTypeDef       DMA_InitStruct = {0};
    FL_DMA_ConfigTypeDef     DMA_ConfigStruct;
    
    DMA_InitStruct.periphAddress        = FL_DMA_PERIPHERAL_FUNCTION1;              /*! DMA外设映射地址 */
    DMA_InitStruct.direction            = FL_DMA_DIR_PERIPHERAL_TO_RAM;             /*! DMA传输方向 */
    DMA_InitStruct.memoryAddressIncMode = FL_DMA_MEMORY_INC_MODE_INCREASE;          /*! RAM地址增长方向 */
    DMA_InitStruct.dataSize             = FL_DMA_BANDWIDTH_16B;                     /*! DAM传输通道数据位宽 */
    DMA_InitStruct.priority             = FL_DMA_PRIORITY_HIGH;                     /*! DMA通道优先级 */
    DMA_InitStruct.circMode             = FL_DISABLE;                               /*! 循环模式使能 */
    FL_DMA_Init(DMA, &DMA_InitStruct, FL_DMA_CHANNEL_4);
    
    FL_DMA_Enable(DMA);
    
    DMA_ConfigStruct.memoryAddress      = (uint32_t)buffer;                         /* DMA传输RAM地址 */
    DMA_ConfigStruct.transmissionCount  = length - 1;                               /* DMA传输请求次数 */
    
    FL_DMA_StartTransmission(DMA, &DMA_ConfigStruct, FL_DMA_CHANNEL_4);             /* 启动DMA传输 */
}

/*****************************************************************************
 * 函数:GetDMAChannelSample
 * 功能:获取DMA_ADC通道采样值
 * 参数:
 * 返回:
 * 说明:只有FL_DMA_CHANNEL_0和FL_DMA_CHANNEL_4能够用于ADC
 ****************************************************************************/
void GetDMAChannelSample(void)
{
    uint16_t DMA_TransferComplete_Time = 0; /* DMA转换超时标志 */

    FL_VREF_EnableVREFBuffer(VREF);                            /* 使能VREF BUFFER */
    FL_ADC_EnableSequencerChannel(ADC, IoHwAb_Channel_TAIL);   /* 通道选择ADC_8 */
    FL_ADC_EnableSequencerChannel(ADC, IoHwAb_Channel_STOP);   /* 通道选择ADC_9 */
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_AVREF); /* 通道选择AVREF */

    ADC_DMA(DMAResult, ADC_Input_Number);

    FL_ADC_ClearFlag_EndOfConversion(ADC); /* 清标志 */
    FL_ADC_Enable(ADC);                    /* 启动ADC */
    FL_ADC_EnableSWConversion(ADC);        /* 开始转换 */

    /* 等待转换完成 */
    do
    {
        DMA_TransferComplete_Time++;
    } while ((!FL_DMA_IsActiveFlag_TransferComplete(DMA, FL_DMA_CHANNEL_4)) && (DMA_TransferComplete_Time < DMA_Translate_Timeout));
    ADC_TimeOutFlag = (DMA_TransferComplete_Time >= DMA_Translate_Timeout) ? 1 : 0;

    FL_DMA_ClearFlag_TransferComplete(DMA, FL_DMA_CHANNEL_4);
    FL_ADC_Disable(ADC);                                     /* 关闭ADC */
    FL_ADC_DisableSequencerChannel(ADC, FL_ADC_ALL_CHANNEL); /* 关闭所有通道 */

    ADC_IntFinishFlag = 1;
}

/*****************************************************************************
 * 函数:ADC_Getdata
 * 功能:获取对应通道的电压或AD值
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
uint32_t ADC_Getdata(uint16_t channel)
{
    uint32_t ret = 0;
#if 1 //获取电压
    if (channel == IoHwAb_Channel_TAIL)
    {
        ret = (uint32_t)(((uint64_t)DMAResult[0] * (ADC_VREF)) / ((uint64_t)DMAResult[ADC_Input_Number - 1] * 10));
    }
    else if (channel == IoHwAb_Channel_STOP)
    {
        ret = (uint32_t)(((uint64_t)DMAResult[1] * (ADC_VREF)) / ((uint64_t)DMAResult[ADC_Input_Number - 1] * 10));
    }
#else //获取AD值
    if (channel == IoHwAb_Channel_TAIL)
    {
        ret = (uint32_t)(((uint64_t)DMAResult[0];
    }
    else if (channel == IoHwAb_Channel_STOP)
    {
        ret = (uint32_t)(((uint64_t)DMAResult[1];
    }
#endif
    return ret;
}

/*****************************************************************************
 * 函数:BSTIM_IRQHandler
 * 功能:更新任务调度器
 * 参数:
 * 返回:
 * 说明:BSTIM中断处理函数
*****************************************************************************/
void BSTIM_IRQHandler(void)
{
  if(FL_BSTIM32_IsEnabledIT_Update(BSTIM32) && FL_BSTIM32_IsActiveFlag_Update(BSTIM32))
  {
    SCH_Update();                             /*调用任务调度函数*/
    FL_BSTIM32_ClearFlag_Update(BSTIM32);     /*清楚BSTIM中断标志*/
  }
}

/*****************************************************************************
 * 函数:BSTIM_Init
 * 功能:BSTIM定时器初始化
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void BSTIM_Init(void)
{
    /* 配置定时周期为1ms */
    FL_BSTIM32_InitTypeDef    defaultInitStruct;
    defaultInitStruct.prescaler       = 16-1; //32M / 16 = 2M
    defaultInitStruct.autoReload      = 2000-1;  //计数2000，定时1MS
    defaultInitStruct.autoReloadState = FL_ENABLE;
    defaultInitStruct.clockSource     = FL_RCC_BSTIM32_CLK_SOURCE_APB2CLK;

    FL_BSTIM32_Init(BSTIM32,&defaultInitStruct );

    FL_BSTIM32_ClearFlag_Update(BSTIM32);
    FL_BSTIM32_Enable(BSTIM32);
    
    FL_BSTIM32_ClearFlag_Update(BSTIM32);    /* 清除计数器中断标志位 */
    FL_BSTIM32_EnableIT_Update(BSTIM32);     /* 开启计数器中断 */
    
    NVIC_DisableIRQ(BSTIM_IRQn);
    NVIC_SetPriority(BSTIM_IRQn, 2);        /* 中断优先级配置 */
    NVIC_EnableIRQ(BSTIM_IRQn); 
}

/*****************************************************************************
 * 函数:GPTIM_Output_Init
 * 功能:GPTIM1 PWM输出初始化
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void GPTIM0_Output_Init(void)
{
    FL_GPTIM_InitTypeDef        timInit;
    FL_GPTIM_OC_InitTypeDef     timOCInit;
    FL_GPIO_InitTypeDef         gpioInit = {0};

    gpioInit.pin          = TAIL1_PIN | TAIL2_PIN;
    gpioInit.mode         = FL_GPIO_MODE_DIGITAL;
    gpioInit.outputType   = FL_GPIO_OUTPUT_PUSHPULL;
    gpioInit.pull         = FL_DISABLE;
    gpioInit.remapPin     = FL_ENABLE;
    FL_GPIO_Init(TAIL_PORT, &gpioInit);

    timInit.prescaler             = 80 - 1;                      /* 分频系数100 */
    timInit.counterMode           = FL_GPTIM_COUNTER_DIR_UP;      /* 向上计数 */
    timInit.autoReload            = 1000 - 1;                     /* 自动重装载值800 */
    timInit.clockDivision         = FL_GPTIM_CLK_DIVISION_DIV1;   /* 死区和滤波分频 */
    timInit.autoReloadState       = FL_ENABLE;                    /* 预装载preload使能 */
    FL_GPTIM_Init(GPTIM0, &timInit);

    timOCInit.OCMode       = FL_GPTIM_OC_MODE_PWM1;               /* 输出比较模式PWM1 */
    timOCInit.OCETRFStatus = FL_DISABLE;                          /* OC1REF不受ETR影响 */
    timOCInit.OCFastMode   = FL_DISABLE;                          /* 关闭快速使能 */
    timOCInit.compareValue = 0;                                   /* 比较值0 初始化输出低电平 */
    timOCInit.OCPolarity   = FL_GPTIM_OC_POLARITY_NORMAL;         /* OC正常输出 */
    timOCInit.OCPreload    = FL_DISABLE;                          /* OC preload 无效 */
    FL_GPTIM_OC_Init(GPTIM0, TAIL1_CHID, &timOCInit);
    FL_GPTIM_OC_Init(GPTIM0, TAIL2_CHID, &timOCInit);

    FL_GPTIM_Enable(GPTIM0);    /* 使能定时器 */
}

/*****************************************************************************
 * 函数:GPTIM2_Output_Init
 * 功能:GPTIM1 PWM输出初始化
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void GPTIM1_Output_Init(void)
{
    FL_GPTIM_InitTypeDef        timInit;
    FL_GPTIM_OC_InitTypeDef     timOCInit;
    FL_GPIO_InitTypeDef         gpioInit = {0};;



    gpioInit.pin          = TAIL3_PIN;
    gpioInit.mode         = FL_GPIO_MODE_DIGITAL;
    gpioInit.outputType   = FL_GPIO_OUTPUT_PUSHPULL;
    gpioInit.pull         = FL_DISABLE;
    gpioInit.remapPin     = FL_DISABLE;
    FL_GPIO_Init(TAIL3_PORT, &gpioInit);

    timInit.prescaler             = 80 - 1;                      /* 分频系数100 */
    timInit.counterMode           = FL_GPTIM_COUNTER_DIR_UP;      /* 向上计数 */
    timInit.autoReload            = 1000 - 1;                     /* 自动重装载值800 */
    timInit.clockDivision         = FL_GPTIM_CLK_DIVISION_DIV1;   /* 死区和滤波分频 */
    timInit.autoReloadState       = FL_ENABLE;                    /* 预装载preload使能 */
    FL_GPTIM_Init(GPTIM1, &timInit);

    timOCInit.OCMode       = FL_GPTIM_OC_MODE_PWM1;               /* 输出比较模式PWM1 */
    timOCInit.OCETRFStatus = FL_DISABLE;                          /* OC1REF不受ETR影响 */
    timOCInit.OCFastMode   = FL_DISABLE;                          /* 关闭快速使能 */
    timOCInit.compareValue = 0;                                   /* 比较值0 初始化输出低电平 */
    timOCInit.OCPolarity   = FL_GPTIM_OC_POLARITY_NORMAL;         /* OC正常输出 */
    timOCInit.OCPreload    = FL_DISABLE;                          /* OC preload 无效 */
    
    FL_GPTIM_OC_Init(GPTIM1, TAIL3_CHID, &timOCInit);

    FL_GPTIM_Enable(GPTIM1);    /* 使能定时器 */
}

/*****************************************************************************
 * 函数:LPTIM32_Setup
 * 功能:
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void LPTIM32_Setup(void)
{
    FL_LPTIM32_InitTypeDef timInit;

    /*---------------- 定时器时间基准配置 ----------------*/
    FL_LPTIM32_StructInit(&timInit);

    timInit.clockSource          = FL_RCC_LPTIM32_CLK_SOURCE_APB1CLK;
    timInit.mode                 = FL_LPTIM32_OPERATION_MODE_NORMAL;
    timInit.prescalerClockSource = FL_LPTIM32_CLK_SOURCE_INTERNAL;
    timInit.prescaler            = FL_LPTIM32_PSC_DIV16;
    timInit.autoReload           = 0xFFFFFFFF;
    timInit.onePulseMode         = FL_LPTIM32_ONE_PULSE_MODE_CONTINUOUS;
    timInit.triggerEdge          = FL_LPTIM32_ETR_TRIGGER_EDGE_RISING;
    timInit.countEdge            = FL_LPTIM32_ETR_COUNT_EDGE_RISING;
    FL_LPTIM32_Init(LPTIM32, &timInit);

    /* 使能LPTIM32 */
    FL_LPTIM32_Enable(LPTIM32);
}
/*****************************************************************************
 * 函数:GPIO_Init
 * 功能:GPIO初始化
 * 参数:
 * 返回:
 * 说明:配置GPIO输出引脚
*****************************************************************************/
void GPIO_Init(void)
{

    FL_GPIO_InitTypeDef GPIO_InitStructA = {0};
    FL_GPIO_InitTypeDef GPIO_InitStructC = {0};

    /*配置PA13为IO输入，用来区分灯具左右边*/
    GPIO_InitStructA.pin        = FL_GPIO_PIN_13;//配置GPIO引脚
    GPIO_InitStructA.mode       = FL_GPIO_MODE_INPUT;        //配置GPIO模式
    GPIO_InitStructA.outputType = FL_GPIO_OUTPUT_PUSHPULL;    //配置GPIO输出类型
    GPIO_InitStructA.pull       = FL_DISABLE;                 //配置GPIO上拉使能
    GPIO_InitStructA.remapPin   = FL_DISABLE;                  //配置GPIO重映射
    FL_GPIO_Init(GPIOA, &GPIO_InitStructA); /* GPIOA */
    
    GPIO_InitStructC.pin       = BM_PIN | STOP1_PIN | STOP2_PIN;//配置GPIO引脚
    GPIO_InitStructC.mode       = FL_GPIO_MODE_OUTPUT;
    GPIO_InitStructC.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStructC.pull       = FL_DISABLE;
    GPIO_InitStructC.remapPin   = FL_DISABLE;
    FL_GPIO_Init(GPIOC, &GPIO_InitStructC); /* GPIOC */
    
}

                           /*****************************************************************************
 * 函数:GPIO_interrupt_init
 * 功能:配置使用IO口中断端口PA8，双边沿触发
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void GPIO_interrupt_init(void)
{
    FL_GPIO_InitTypeDef gpioInitStruct = {0};
    FL_EXTI_InitTypeDef extiInitStruct = {0};
    FL_EXTI_CommonInitTypeDef  extiCommonInitStruct = {0};

    //FL_RCC_EnableEXTIOnSleep();/* 休眠使能外部中断采样*/
    
    /* EXTI中断采样时钟选择 */
    extiCommonInitStruct.clockSource = FL_RCC_EXTI_CLK_SOURCE_LSCLK;
    FL_EXTI_CommonInit(&extiCommonInitStruct);

    /* 用到的GPIO引脚    设为输入*/
    gpioInitStruct.pin        = WELCOME_SIG_PIN;
    gpioInitStruct.mode       = FL_GPIO_MODE_INPUT;
    gpioInitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    gpioInitStruct.pull       = FL_ENABLE;
    gpioInitStruct.remapPin   = FL_DISABLE;
    FL_GPIO_Init(WELCOME_SIG_PORT, &gpioInitStruct);


    extiInitStruct.input       = FL_GPIO_EXTI_INPUT_GROUP0;         /* 中断线上对应的IO */
    extiInitStruct.filter      = FL_ENABLE;                         /* 数字滤波使能选择 */
    extiInitStruct.triggerEdge = FL_GPIO_EXTI_TRIGGER_EDGE_BOTH; /* 设置触发边沿 */
    FL_EXTI_Init(FL_GPIO_EXTI_LINE_2,&extiInitStruct);    


    /*NVIC中断配置*/
    NVIC_DisableIRQ(GPIO_IRQn);
    NVIC_SetPriority(GPIO_IRQn, 2); /* 中断优先级配置 */
    NVIC_EnableIRQ(GPIO_IRQn);
}

/*****************************************************************************
 * 函数:GPIO_IRQHandler
 * 功能:GPIO中断处理函数，配合LPTIM32捕获PWM输入信号，计算频率和占空比
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void GPIO_IRQHandler(void)
{
    static uint8_t FilterCnt = 4;
    uint32_t duty = 0;
    uint32_t freq = 0;
    uint8_t RisingEdge = 0;

    if (FL_GPIO_IsActiveFlag_EXTI(GPIO, FL_GPIO_EXTI_LINE_2) && FL_GPIO_GetEXTILine(GPIO, FL_GPIO_EXTI_LINE_2))
    {
        /* 保存捕获值 */
        RisingEdge = 1;
        ccvValNow = LPTIM32->CNT;
        FL_GPIO_ClearFlag_EXTI(GPIO, FL_GPIO_EXTI_LINE_2);
    }
    else
    {
        ccvValNow = LPTIM32->CNT;
        FL_GPIO_ClearFlag_EXTI(GPIO, FL_GPIO_EXTI_LINE_2);
    }

    if (RisingEdge == 1)
    {
        if (ccvValNow <= ccvValPrev)
        {
            getccvLow = ccvValNow + 0xFFFFFFFF - ccvValPrev;
        }
        else
        {
            getccvLow = ccvValNow - ccvValPrev;
        }
    }
    else
    {
        if (ccvValNow <= ccvValPrev)
        {
            getccvHigh = ccvValNow + 0xFFFFFFFF - ccvValPrev;
        }
        else
        {
            getccvHigh = ccvValNow - ccvValPrev;
        }
    }

    if (FilterCnt > 0)
    {
        FilterCnt--;
    }
    else
    {
        duty = (getccvHigh * 1000) / (getccvHigh + getccvLow);
        freq = PWM_Input_COUNTER / (getccvHigh + getccvLow);
        Led_App_Animation_Det(freq, duty);
    }
    ccvValPrev = ccvValNow;
}
/*****************************************************************************
 * 函数:SetGpioOutPutValue
 * 功能:设置GPIO输出值
 * 参数:GPIOx:GPIO端口GPIOA,GPIOB,GPIOC,GPIOD  pin:GPIO引脚号   value:GPIO输出值
 * 返回:
 * 说明:
*****************************************************************************/
void SetGpioOutPutValue(GPIO_Type *GPIOx, uint32_t pin, uint8_t value)
{
    if (value)
    {
        FL_GPIO_SetOutputPin(GPIOx, pin);
    }
    else
    {
        FL_GPIO_ResetOutputPin(GPIOx, pin);
    }
}

/*****************************************************************************
 * 函数:Read_Right_or_Left_light
 * 功能:识别灯具位置，左边或右边
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void Read_Right_or_Left_light(void)
{
    if (FL_GPIO_GetInputPin(GPIOA, FL_GPIO_PIN_13) == 0)
    {
        Left_or_Right = RIGHT;
    }
    else
    {
        Left_or_Right = LEFT;
    }
}
                           
/*****************************************************************************
 * 函数:Check_PLL_State
 * 功能:停振检测及处理由外部时钟源切换回内部时钟源
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void Check_PLL_State(void)
{
    if(SYSCLKState == SYSCLK_ERROR)
    {
        /* 判断是否发生XTHF停振或PLL失锁事件，如有及时切回主系统时钟 */
        SwtichToMainSystemClock(&RCHF_InitParameter, &XTHF_InitParameter, &PLL_InitParameter);
    }
}

/*****************************************************************************
 * 函数:Clock_Init
 * 功能:时钟初始化
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void Clock_Init(void)
{
    SelXTHFToPLL(&XTHF_InitParameter,&PLL_InitParameter);
}

 /*****************************************************************************
 * 函数:IWDT初始化
 * 功能:看门狗初始化
 * 参数:u32OverFlowPeriod: 看门狗溢出时间
 * 返回:FL_FAIL: 初始化失败；FL_PASS: 初始化成功
 * 说明:
*****************************************************************************/

FL_ErrorStatus IWDT_Init(uint32_t u32OverFlowPeriod)
{
    FL_IWDT_InitTypeDef IWDT_InitStruct;

    /* 默认不使用窗口 */
    IWDT_InitStruct.iwdtWindows = 0;

    /*最长溢出时间*/
    IWDT_InitStruct.overflowPeriod = u32OverFlowPeriod;

    return FL_IWDT_Init(IWDT, &IWDT_InitStruct);
}


/*****************************************************************************
 * 函数:IWDT清除计数
 * 功能:喂狗
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void IWDT_Clr(void)
{
    FL_IWDT_ReloadCounter(IWDT);
}

/*****************************************************************************
 * 函数:PowerDownMonitoring
 * 功能:掉电监控，用于执行掉电事件
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void PowerDownMonitoring(void)
{
    /* 确认SVD监测结果是否低于阈值 */
    if (true == SVD_Result_Confirmed(SVD_BELOW_THRESHOLD, 1U))
    {   /* 防抖处理 */
        if (true == SVD_Result_Confirmed(SVD_BELOW_THRESHOLD, 2000U/*us*/))
        {
            /* 电压下降到报警阈值，处理掉电事件 */
            /* 用户程序1 */
            /* ...... */
            /* 注意：用户需确保在BOR复位之前执行完毕 */
            /* 确认SVD监测结果是否高于阈值，如否则持续等待 */
            while(false == SVD_Result_Confirmed(SVD_HIGHER_THRESHOLD, 20U/*us*/));
            /* 由于电源有下降到报警阈值，软件复位后重新初始化 */
            RMU_Soft_SystemReset();
        }
    }
}

/*****************************************************************************
 * 函数:Improve_Reliability
 * 功能:系统初始化前监控电源电压，电源稳定后进行初始化，提高系统稳定性
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void Improve_Reliability(void)
{
    /*****************提高可靠性（IWDT/SVD/BOR）*****************/  
    /* Initialize FL Driver Library */
    /* SHOULD BE KEPT!!! */
    FL_Init();
  
    /* 使能SVD, 阈值4.376V(falling)~4.500(rising) */
    SVD_Init(SVD_MONTIOR_VDD, FL_SVD_WARNING_THRESHOLD_GROUP11, FL_SVD_REFERENCE_1P0V);
  
    /* 确认SVD监测结果是否高于阈值，如否则持续等待，等待电压高于4.16V后程序再往后执行 */
    while(false == SVD_Result_Confirmed(SVD_HIGHER_THRESHOLD, 200U/*us*/));
  
    /* 使能BOR 提高BOR档位至1.75V*/
    RMU_BOR_Init(FL_RMU_BOR_THRESHOLD_1P75V);
    /*****************提高可靠性（IWDT/SVD/BOR）*****************/
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    /* SHOULD BE KEPT!!! */
    MF_Clock_Init();
}

/*****************************************************************************
 * 函数:System_Init
 * 功能:系统初始化
 * 参数:
 * 返回:
 * 说明:
*****************************************************************************/
void System_Init(void)
{
    IWDT_Init(FL_IWDT_PERIOD_250MS); // 看门狗初始化250ms复位

    Improve_Reliability();

    Clock_Init();

    GPIO_Init();
    
    GPIO_interrupt_init();

    Read_Right_or_Left_light();

    ADC_Init();

    GPTIM0_Output_Init();

    GPTIM1_Output_Init();

    LPTIM32_Setup();

    SensorGroup_Init();

    Led_App_Init();
    
    Led_App_CloseAllLight();
    
}
/******************************************************************************************************************************
#end file
******************************************************************************************************************************/
